﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
		<title>StauffConsulting.Xml.Xerialization &ndash; Tutorial</title>
		<link href="../../documentation/Stauffware.css" rel="StyleSheet" type="text/css" media="screen, print" />
		<style type="text/css">
			.example	{ font-family:Monospace; }
			td.example { white-space:nowrap; }
		</style>
	</head>
	<body>
	<h1 align="center">StauffConsulting.Xml.Xerialization &ndash; Tutorial</h1>

	<p>The <code>StauffConsulting.Xml.Xerialization</code> namespace contains a 
		class library for serializing .Net objects to and from XML.</p>

	<h3>Design Goals &amp; Principles</h3>

	<ul>
		<li>Minimize impact when adding serialization to existing classes.  
			Maintaining the integrity of the application code is more important 
			than optimizing the XML representation or I/O performance.</li>

		<li>Provide intelligent default behavior; that is, you shouldn't have 
			to tag every class member to get reasonable behaviour.</li>

		<li>Provide support for inheritence and generics.</li>

		<li>Allow the user (programmer) to specify whether class member values 
			get stored as XML attributes, XML elements, or XML text.</li>

		<li>When deserializing (reading XML), be insensitive to the order of XML 
			attributes and sibling elements when the order doesn’t matter.</li>

		<li>Maintain the ordering of lists of objects serialized as XML child elements.</li>

		<li>Provide support for self-referential and circular data structures.
			<span style="color:#FF0000">(Not available yet.)</span></li>

		<li>Provide support for versioning.
			<span style="color:#FF0000">(Not available yet.)</span></li>

		<li>Allow straightforward customization of [de]serialization 
			behaviour where appropriate.</li>

		<li>Support fragmentary I/O; that is, don't require that [de]serialization 
			always start with a special document-level object.</li>
	</ul>

	<h2>Quick-Start Tutorial</h2>

	<p>
	This library was designed especially for situations where you want to add XML 
	serialization to some existing classes with a minimal amount of extra work, 
	so let's use that as a starting point.
	</p>

	<h3>The <code>XerialContext</code> class</h3>

	<p>This is the top-level xerialization object that holds or controls everything else.
	You can't xerialize or dexerialize without one, but that's the only absolute
	requirement, and creating one is easy:</p>

	<blockquote><code>
		XerialContext myContext = new XerialContext(true);
	</code></blockquote>

    <p>The one required parameter (a boolean) specifies whether to ignore the case of XML 
	attribute and element names.  Xerialization and dexerialization are equally easy:</p>

	<blockquote><code>
		myContext.WriteToXml(myObjectToSerialize, "MyNewFile.xml");<br />
		&nbsp;&nbsp;&nbsp;&bull;&bull;&bull;<br />
		mynewObject.ReadFromXml("MyOldFile.xml");
	</code></blockquote>

	<p>The <code>WriteToXml</code> method has overloads for sending the XML output to a file 
	(specified by name), a <code>TextWriter</code> or an <code>XmlTextWriter</code>.<br />
	The <code>ReadFromXml</code> method has overloads for reading from a file (specified
	by name), a <code>TextReader</code>, or an <code>XmlTextReader</code>.<br />
	In addition, you can optionally tell <code>ReadFromXml</code> the root element
	name to expect, and/or provide it with an <code>XmlErrorReporter</code> delegate
	for reporting non-fatal errors.</p>

	<h3>But what gets xerialized?  And in what form?</h3>
	<p>
	The object passed to <code>WriteToXml</code> is represented in XML as an XML
	element whose name is the (short) name of the object's class.  The members (contents)
	of the object are (by default) represented according to the following rules, which are evaluated
	in the order given:
	</p>
	<ol>
		<li>Static members are never xerialized.</li>
		<li>Constructors, methods, events and delegates are never xerialized.</li>
		<li>Constants are never serialized.</li>
		<li>Members of all visibilities (public, protected, internal, and private) can be xerialized
			(subject to security restrictions). </li>
		<li>If the object inherits any members from a base class, those inherited members
			are xerialized first.  (The members of <code>System.Object</code> are not included.)</li>
		<li>A member with a primitive value type (integers, floats, decimal, char and boolean) 
			is xerialized as an XML attribute whose name is the name of the member.</li>
		<li>A member of type string is xerialized as an XML attribute; "special"
			characters are encoded using standard HTML entities (e.g. &amp;).</li>
		<li>A member whose type is an enum is xerialized as an XML attribute who value
			is the enum value name (<i>not</i> the integer value).</li>
		<li>A member whose type implements <code>IList</code> (which includes arrays) is
			xerialized as an XML child element whose name is the member name.  
			That element in turn contains one child element for each item in the list,
			by applying this set of rules recursively.</li>
		<li>A member whose value is a class or a struct is xerialized as an XML child element
			whose name is the member name.  That element in turn contains a child element
			which represents the value of the member, by applying this set of rules recursively.</li>
	</ol>
	<p>Abstract and generic types are fully supported.</p>  
	<p>Dexerialization requires no special constructors (e.g. parameterless constructors).
		However, if the object being xerialized has no suitable constructor, 
		an uninitialized object is created using
		<code>System&#8203;.&#8203;Runtime&#8203;.&#8203;Serialization&#8203;.&#8203;FormatterServices&#8203;.&#8203;GetUninitializedObject</code>.
		<i>Uninitialized</i> means that space for the object is allocated and cleared to zero
		byte values, but (a) no constructor is called, and (b) field initialization does not happen.
	</p>

	<p>So, while you can xerialize an object "without having to do anything", you
		probably won't get quite what you want.  Here are some potential issues
		with the default behavior:</p>
		
	<ul>
		<li>If you have a public read/write property that wraps a private field, then both
			the property and the field will get xerialized, which is, at best, redundant.</li>
		<li>If you try to xerialize two classes with the same (short) name but from different
			namespaces, the resulting XML name collision will throw an exception.</li>
	</ul>

	<p>Fortunately, the library provides a number of tools for modifying these default behaviors.</p>


	<h3>The <code>MemberInclusion</code> enum</h3>

	<p>This enumeration specifies how to decide whether to include a class member
		in xerialization, based on its visibility:</p>

		<table border="0">
			<tr><td><code><b>Public</b> &nbsp; </code></td>
				<td>Indicates that public members should be included.</td>
			</tr>
			<tr><td><code><b>Internal</b> &nbsp; </code></td>
				<td>Indicates that internal (assembly) members should be included.</td>
			</tr>
			<tr><td><code><b>Protected</b> &nbsp; </code></td>
				<td>Indicates that protected (family) members should be included.</td>
			</tr>
			<tr><td><code><b>Private</b> &nbsp; </code></td>
				<td>Indicates that private members should be included.</td>
			</tr>
		</table>

		<p><code>MemberInclusion</code> has the <code>[Flags]</code> attribute,
			making it a bit field, so you can combine values with the bitwise OR operator.
			Hence, this enum type defines two additional values:
		</p>
		<table border="0">
			<tr><td><code><b>All</b> &nbsp; </code></td>
				<td>Indicates that all members should be included.  This is equivalent to
					<code>Public | Internal | Protected | Private</code></td>
			</tr>
			<tr><td><code><b>None</b> &nbsp; </code></td>
				<td>Indicates that no members should be included.</td>
			</tr>
		</table>

		<p>You can use this enum in the following properties of <code>XerialContext</code>:</p>

		<dl>
			<dt><code>MemberInclusion <b>DefaultFieldInclusion</b> { get; set; }</code></dt>
			<dd>Specifies the default MemberInclusion for fields.  Its default value is <code>All</code>.</dd>
			<dt><code>MemberInclusion <b>DefaultPropertyInclusion</b> { get; set; }</code></dt>
			<dd>Specifies the default MemberInclusion for properties.  Its default value is <code>All</code>.</dd>
		</dl>

		<p>You can override these defaults on specific classes, as you'll see below.</p>

	<h3>The <code>MemberValueEncoding</code> enum</h3>

		<p>
			This enum specifies how a member is to be represented in XML.
			Examples are provided for a member named "birth" with the type <code>DateTime</code>
			in a class named "person". 
		</p>

		<table class="light" style="margin-bottom:1em">
			<tr><th>Enum Value</th><th>Description</th><th>Examples</th></tr>
			<tr valign="top"><td><code><b>Attribute</b></code></td>
				<td>The member is xerialized as an XML attribute of the member's 
					parent element.  The member name is used as the attribute name, and 
					the member value is the attribute value.  The member value type is 
					implicit.  
				</td>
				<td class="example">&lt;person birth="12&nbsp;May&nbsp;1987"/&gt;	</td>
			</tr>
		,
			<tr valign="top"><td><code><b>NestedElements</b></code></td>
				<td>the member is xerialized as its own XML element, which 
					encloses another XML element whose name identifies the value type and 
					contains the value.  Because the value type is explicit, this works
					well when the value could be a subclass of the member type.
				</td>
				<td class="example">
					&lt;person&gt;<br />
					&nbsp;&nbsp;&nbsp;&lt;birth&gt;<br />
					&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;date&gt;12&nbsp;May&nbsp;1987&lt;/date&gt;<br />
					&nbsp;&nbsp;&nbsp;&lt;/birth&gt;<br />
					&lt;/person&gt;<br />	
					&lt;person&gt;<br />
					&nbsp;&nbsp;&nbsp;&lt;birth&gt;<br />
					&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;date&nbsp;d="12"&nbsp;m="May"<br />
					&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y="1987"/&gt;<br />
					&nbsp;&nbsp;&nbsp;&lt;/birth&gt;<br />
					&lt;/person&gt;
				</td>
			</tr>

			<tr valign="top"><td><code><b>ImplicitValueType</b></code></td>
				<td>Here the member value has no XML element of its own; 
					it is stored in the content and/or attributes of the member's XML element.
					The value type is implicit, and therefore must be exactly the same as the
					member type, and not a subclass.
					(FUTURE: or the target type must have a suitable static factory method.)
				</td>
				<td class="example">
					&lt;person&gt;<br />
					&nbsp;&nbsp;&nbsp;&lt;birth&gt;12 May 1987&lt;/birth&gt;<br />
					&lt;/person&gt;	<br />
					&lt;person&gt;<br />
					&nbsp;&nbsp;&nbsp;&lt;birth d="12" m="May" y="1987"/&gt;<br />
					&lt;/person&gt;	
				</td>
			</tr>

			<tr valign="top"><td><code><b>ImplicitMemberName&nbsp;&nbsp;</b></code></td>
				<td>Here the member has no XML element of its own; the value
					element is a direct child of the member's parent element.  This encoding
					can be used only if the member value type is not be used for any other 
					xerialized member of the member's class or ancestor classes.
				</td>
				<td class="example">
					&lt;person&gt;<br />
					&nbsp;&nbsp;&nbsp;&lt;date&gt;12 May 1987&lt;/date&gt;<br />
					&lt;/person&gt;<br />
					&lt;person&gt;<br />
					&nbsp;&nbsp;&nbsp;&lt;date d="12" m="May" y="1987"/&gt;<br />
					&lt;/person&gt;
				</td>
			</tr>

			<tr valign="top"><td><code><b>Text&nbsp;&nbsp;</b></code></td>
				<td>The member value is xerialized as text content of the parent element.
					Both the member name and the value type are implicit.  This encoding
					cannot be used by more than one member of a class.
				</td>
				<td class="example">
					&lt;person&gt;12 May 1987&lt;/person&gt;
				</td>
			</tr>
			<tr valign="top"><td><code><b>CustomAttribute&nbsp;&nbsp;</b></code></td>
				<td>The member is xerialized by custom methods provided by the user,
					during the processing of XML attributes.
				</td>
			</tr>
			<tr valign="top"><td><code><b>CustomContent&nbsp;&nbsp;</b></code></td>
				<td>The member is xerialized by custom methods provided by the user,
					during the processing of XML text and/or child elements.
				</td>
			</tr>
			<tr valign="top"><td><code><b>Omit</b></code></td>
				<td>This prevents the member and its value from be xerialized at all.
				</td>
			</tr>
			<tr valign="top"><td><code><b>Default</b></code></td>
				<td>Use the default encoding.
				</td>
			</tr>
		</table>

		<p>You can use this enum in the following properties of <code>XerialContext</code>:</p>

		<dl>
			<dt><code>MemberValueEncoding <b>DefaultFieldEncoding</b> { get; set; }</code></dt>
			<dd>Specifies the default encoding for fields.  Its default value is <code>Default</code>.</dd>
			<dt><code>MemberValueEncoding <b>DefaultPropertyEncoding</b> { get; set; }</code></dt>
			<dd>Specifies the default encoding for properties.  Its default value is <code>Default</code>.</dd>
		</dl>

		<p>You can override these defaults on specific classes, as you'll see below.</p>


	<h3><code>XerialTypeAttribute</code></h3>

	<p>This is a custom attribute that you can apply to a class or struct to override
		its xerialization behavior.  The attribute parameters are all optional and named:</p>


	<p><b><span style="color:red">(TUTORIAL NOT FINISHED)</span></b></p>
	

	<h3><code>XerialMemberAttribute</code></h3>


	<h2>Strategies for Customization</h2>

	<h3>Use <code>XerialMemberAttribute.ReadMethod</code> and <code>.WriteMethod</code></h3>

	<h3>Create a subclass of <code>XerialScalarMapping</code></h3>

	Sample code:<br />
<pre>
// The data type to be Xerialized : immutable Rational, passed by value
public struct Rational
{
    public int Numerator { get; private set; }
    public int Denominator { get; private set; }

    public Rational (int numerator, int denominator)
    {
        this.Numerator = (denominator &lt; 0) ? -numerator : numerator;
        this.Denominator = (denominator &lt; 0) ? -denominator : denominator;
    }
    
    public Rational (string str)
    {
        // ... implementation left as an exercise for the reader ...
    }

    public override string ToString ( ) 
    { 
        return this.Numerator.ToString() + "/" + this.Denominator.ToString(); 
    }

    // ... remaining methods left up to the imagination of the reader ...
}

// This class is all you have to provide to support Xerialization of
// the Rational type.
public class RationalXMapping : XerialScalarMapping
{
    // boilerplate constructor
    public RationalXMapping (XerialContext context) : base(context, typeof(Rational)) { }

    // converts a string to the data type being mapped
    protected override ParseResult FromXmlString (string valueString)
    {
        try
        {
            Rational value = new Rational(valueString);
            return new ParseResult(value, null);
        }
        catch (FormatException x)
        {
            return new ParseResult(null, x.Message);
        }
    }
    
    // This method is included for completeness, but for this example 
    // it isn't needed because the inherited method just calls ToString().
    
    protected override string ToXmlString (object value) 
    {    return ((Rational) value).ToString();    }
}
</pre>



	</body>
</html>

<!--

	<table><tr valign="top"><td>
<pre>public class <b>Zoo</b>
{
    public List&lt;Exhibit&gt; Exhibits = 
                      new List&lt;Exhibit&gt;();
}

public class <b>Exhibit</b>
{
    public Enclosure Enclosure;
    public List&lt;Animal&gt; Inmates;

    public Exhibit (Enclosure enc, 
                    params Animal[] aa)
    {
        this.Enclosure = enc;
        this.Inmates = new List&lt;Animal&gt;(aa);
    }
}

public enum <b>Barrier</b> 
{    None, Bars, Fence, Moat   }

public abstract class <b>Enclosure</b>
{
    public abstract Barrier Barrier { get; }
    public int Area;

    protected Enclosure (int area)
    {    this.Area = area;    }
}</pre>
</td><td><pre>   </pre></td><td>
<pre>public class <b>Cage</b> : Enclosure
{
    public override Barrier Barrier
    {    get { return Barrier.Bars; }    }

    public Cage (int area) : base(area) { }
}

public class <b>Compound</b> : Enclosure
{
    public override Barrier Barrier
    {    get { return this._barrier; }    }
    private Barrier _barrier;

    public Compound (int area, Barrier b)
        : base(area)
    {
        this._barrier = b;
    }
}

public abstract class <b>Animal</b>
{
    public float Age;
    public string Name;

    protected Animal (string name, float age)
    {
        this.Age = age;
        this.Name = name;
    }
}</pre>
	</td></tr></table>
	
-->
